﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace CodeContrib.Collections.Generic
{
	public class Paged<T> : IPaged<T>, IPaging
	{
		private readonly IEnumerable<T> _data;

		public bool HasNextPage
		{
			get { return (PageNumber < PageCount); }
		}

		public bool HasPreviousPage
		{
			get { return (PageNumber > 1); }
		}

		public bool IsFirstPage
		{
			get { return (PageNumber == 1); }
		}

		public bool IsLastPage
		{
			get { return (PageNumber >= PageCount); }
		}

		public int PageCount { get; private set; }
		public int PageNumber { get; private set; }
		public int PageSize { get; private set; }
		public int TotalCount { get; private set; }

		public Paged(IQueryable<T> query, Paging paging) : this(query, paging.PageNumber, paging.PageSize)
		{
		}

		public Paged(IQueryable<T> query, int pageNumber, int pageSize)
		{
			Guard.NotNull(query, "data");
			Guard.NotNegative(pageNumber, "pageNumber");
			Guard.NotNegative(pageSize, "pageSize");

			PageNumber = pageNumber;
			PageSize = pageSize;
			TotalCount = query.Count();

			_data = query.Skip((pageNumber - 1) * pageSize).Take(pageSize).ToList();

			if (TotalCount > 0)
			{
				PageCount = (int)Math.Ceiling(TotalCount / (double)PageSize);

				if (PageNumber > PageCount)
				{
					PageNumber = PageCount;
				}
			}
			else
			{
				PageCount = 1;
			}
		}

		public IEnumerator<T> GetEnumerator()
		{
			return _data.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return _data.GetEnumerator();
		}
	}
}